use std::fs;
// use std::fs::File;
// use std::io::{BufReader, Read};
use std::path::Path;

use serde::{self};
use x_hash;
// use x_hash::DigestFmt;
use x_io::{directory as XDirectory, file as XFile};

/*#[derive(Serialize, Debug)]
#[serde(rename_all = "camelCase")]
struct MetaData {
    size: u64,
    is_file: bool,
    is_exist: bool,
    is_directory: bool,
}*/

/// 检测文件状态
/*#[tauri::command]
async fn state(path: &Path) -> MetaData {
    if path.exists() {
        let size = if path.is_file() {
            fs::metadata(&path).unwrap().len()
        } else {
            0
        };
        Ok(MetaData {
            size,
            is_file: path.is_file(),
            is_exist: true,
            is_directory: path.is_dir(),
        })
    } else {
        Ok(MetaData {
            size: 0,
            is_file: false,
            is_exist: false,
            is_directory: false,
        })
    }
}*/

/// 检测文件是否存在
#[tauri::command]
async fn check_exist(path: &Path) -> Result<bool, String> {
    if path.exists() {
        Ok(true)
    } else {
        Err("Path does not exist".to_string())
    }
}

/// 确保文件存在, 不存在会创建一个空文件
#[tauri::command]
async fn ensure_exist(path: &Path) -> Result<bool, String> {
    return match XFile::ensure_exist(path) {
        Ok(_) => Ok(true),
        Err(_) => Err("Path processing failed".to_string()),
    };
}

/// 删除文件/文件夹
#[tauri::command]
async fn remove(path: &Path) -> Result<bool, String> {
    if path.is_file() {
        return match XFile::delete(path) {
            Ok(_) => Ok(true),
            Err(_) => Err("Delete file failed".to_string()),
        };
    }
    if path.is_dir() {
        return match XDirectory::delete(path) {
            Ok(_) => Ok(true),
            Err(_) => Err("Delete directory failed".to_string()),
        };
    }
    return Err("Delete path failed".to_string());
}

/// 文件/文件夹重命名
#[tauri::command]
async fn rename(source: &Path, target: &Path) -> Result<bool, String> {
    return match fs::rename(source, target) {
        Ok(_) => Ok(true),
        Err(_) => Err("File/folder rename failed".to_string()),
    };
}

/// 文件/文件夹复制
#[tauri::command]
async fn copy(source: &Path, target: &Path) -> Result<bool, String> {
    if source.is_dir() {
        return match fs::copy(source, target) {
            Ok(_) => Ok(true),
            Err(_) => Err("Copy file failed".to_string()),
        };
    }
    if source.is_file() {
        return match XDirectory::copy(source, target) {
            Ok(_) => Ok(true),
            Err(_) => Err("Copy directory failed".to_string()),
        };
    }
    return Err("Copy path failed".to_string());
}

/// 计算文件的MD5
// #[tauri::command]
// async fn file_md5(file: &Path) -> Result<String, String> {
//     if file.is_file() {
//         let mut digest = x_hash::Md5::new();
//
//         let file = File::open(file).expect("Unable to open file");
//         let mut reader = BufReader::new(file);
//         // 读取文件, 每次读取1024字节
//         let mut buffer: [u8; 1024] = [0; 1024];
//         loop {
//             match reader.read(&mut buffer) {
//                 Ok(0) => {
//                     break;
//                 }
//                 Ok(read_count) => {
//                     digest.update(&buffer[..read_count]);
//                 }
//                 Err(error) => Err(error)
//             }
//         }
//         let md5 = DigestFmt(digest.result()).to_string();
//         return Ok(md5);
//     }
//     return Err("The path is not a file".to_string());
// }

pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
    tauri::plugin::Builder::new("file-extra")
        .invoke_handler(tauri::generate_handler![
            // state,
            check_exist,
            ensure_exist,
            remove,
            rename,
            copy
            // file_md5
        ])
        .build()
}
